オセロAI"Egaroucid"における深層学習の利用
【基本的な情報】
Egaroucidはにゃにゃんが作っているオセロAIである。2021年6月に一瞬だけ世界10位になった。
【関連URL】
GitHub(新しいバージョン&Webサイトのレポジトリ) 【変更履歴】
以前のボツアイデア
最初は盤面における勝率を学習しようとしたが、オセロとは言っても実現可能盤面数はとても多いので、いくら大きなデータセットを使っても勝率を正確に訓練データとして与えられないと判断して、それであればとりあえず終局時の石数差の方が現実的だと思った。
盤面128入力(64マスについて白石、黒石のそれぞれについてあるかないかを表したもの)のみで大きなNNを作って学習させた後に小さいモデルに蒸留する->全然うまく蒸留できなかった。そもそも回帰なので蒸留しにくいのかもしれない知らんけど
2021/09/11 23:22まで
とりあえず盤面の128入力とこれまでの評価関数で使っていた値31個の合計159入力で中間層が128-64のNNを作った。
活性化関数はLeakyReLUでalpha=0.01
loss=mse
optimizer=Adamでlr=0.001
1000局の結果でだいたい44000個の盤面で学習してmae=2.04くらい
https://scrapbox.io/files/613cbcda87ec86001d95f468.png
2021/09/11 23:41
活性化関数をReLUにしただけ。
mae=2.11
だめそう。
https://scrapbox.io/files/613cc01af1c06d0022babbc9.png
2021/09/11 23:48
活性化関数をLeakyReLUのalpha=0.05にした。
mae=2.05
変わらん。
https://scrapbox.io/files/613cc1bfc46984002267871c.png
2021/09/11 23:54
Adamのlr=0.005に増やした。
mae=2.24
だめ。
https://scrapbox.io/files/613cc32dc6a221001d1aa02f.png
2021/09/12 0:03
Adamのlr=0.0005に減らした。
mae=2.04
変わらん。
https://scrapbox.io/files/613cc52d0dddef00233f0bfb.png
2021/09/12 0:14
最適化をSGD(よくわからんのでデフォルト値を使用)にした
mae=2.11
だめ
https://scrapbox.io/files/613cc7e09cc659001ddc34b5.png
2021/09/12 0:44
lossに自前の相対誤差を使用。
mae=2.61
相対誤差の最小化を試みたのでmaeだけでは性能がわからないが、結構いい感じに学習できているので多分評価値が本来の石数差の正負と逆転することはまずないと思う(知らんけど)
↑と思っていたのだが、実際に推論したデータを見るとだめそう。
正解: -6.0, 4.0, 0.0, -4.0, 0.0, 2.0, 0.0, 0.0, -10.0, 4.0
推論: 0.85, -1.23, 0.03, -3.62, 0.01, 0.33, -0.55, 0.19, -1.16, 1.83
そもそもグラフを見るとval_loss(相対誤差)が0.5くらいまでしか落ちていない時点でだめだってことがわかる。
グラフはlossの単位が上と違うので注意
https://scrapbox.io/files/613ccfbdcd866f0022d7d405.png
2021/09/12 0:58
lossをlogcoshにした。引数xについて0付近ではx^2、遠いところではxに比例しているみたいになるので訓練データがおかしい場合にそれに引っ張られにくいらしい。今回は訓練データに出てくる盤面の大半が一回遭遇しただけの盤面なので、訓練データがおかしいことはありそうなので適していそう。
mae=2.11と微妙な感じはするが、でも訓練データを疑った結果なので実際の推論を見てみる。
正解: 12.0, -2.0, 4.0, 2.0, 4.0, -4.0, -2.0, 2.0, -4.0, 8.0
推論: 6.46, -0.58, 4.67, 0.61, 1.17, -1.59, -0.82, -4.85, -0.36, 7.27
たまにヤバいのがあるけどまあ悪くはなさそう(主観が入っている)
https://scrapbox.io/files/613cd2a8785b7900246433d3.png
手数が進むにつれて同じ盤面に出くわす確率は急速に下がるけど、そもそも中盤でも同じ盤面に出くわすことは多分千とか万の局ではそうそうないので、訓練データにどれくらい進行した盤面なのかを加えても良いかもしれない。
終盤になるにつれてloss関数を厳しくする感じにしたいな。
2021/09/12 15:16
結局159入力128-64の1出力、LeakyReLU(0.01)、mse、Adam(0.001)に落ち着いた
mae=2.07
本当はmaeがsub2してほしいが…
正解: -2.0, -4.0, 8.0, -8.0, 8.0, 2.0, 4.0, -6.0, 2.0, 8.0
推論: -2.18, -1.48, 10.06, -7.78, 9.16, 0.52, 3.51, -0.61, 2.24, 6.83
https://scrapbox.io/files/613d9b57fd1201001d0eae78.png
この結果をparam.txtに保存した。
以前作った圧縮アルゴリズムで圧縮すると348KB->29KBとなり、埋め込めそう。
2021/09/12 15:26
前の学習でテストデータと正規化に必要なパラメータを出力し忘れたので再学習。2500局、11万盤面で学習。
mae=2.78
訓練データ増やしたのでmaeが下がりきらなくなったが大目に見ることにする
正解: 2.0, -12.0, 2.0, 9.0, 1.0, 6.0, 0.0, 0.0, 8.0, -2.0
推論: 1.63, -13.86, 3.41, 5.93, 2.75, 1.19, 0.35, 5.31, 5.33, -1.95
https://scrapbox.io/files/613da14b36f5ce001d980ad6.png
圧縮: 343KB->29KB
2021/09/12 15:50
このモデルの入力には以前雑にパラメータ調整したパターン評価を入れているが、パターン評価がメモリもコード長も食い荒らすので一度廃止して学習してみた。
137入力とした以外は以前と同じ。2500局、11万盤面で学習。
mae=2.74
正解: -6.0, -10.0, -4.0, -4.0, 0.0, -6.0, 4.0, -2.0, -4.0, -2.0
推論: -4.06, -4.18, -4.2, -0.21, -0.21, -1.69, 2.45, -0.86, -3.6, -1.9
https://scrapbox.io/files/613da8c8acdf8c0023f2a2ac.png
全然精度落ちていなくて笑った。
137入力に変更して小型化する。
圧縮は309KB->26KB
圧縮アルゴリズムの改善で精度を上げて26KBにできた。
2021/09/12 20:12
137入力では盤面回転を実装していなかったが、しなくてはいけないことに気づいた。
また、手番変更は悪手だと思ったのでやめた。
さらに以前の盤面回転アルゴリズムにバグを見つけた。最悪…
以上を直して2500局、22万盤面で学習。
mae=3.26
答え: -2.0, 9.0, -6.0, -4.0, 0.0, 0.0, 0.0, -2.0, 2.0, -8.0
推論: -0.04, 5.14, -3.0, 0.17, 1.22, -1.25, 4.85, 0.25, 3.67, -3.5
https://scrapbox.io/files/613de69ecea66e00238d83a9.png
そんなに強くないけどまあ弱くはないって感じ
2021/09/12 21:09
全く同じモデルで1000局、88000盤面だけを使って学習。
なぜか学習データが少ない方が**テストデータでの**成績が良かったりするので…(小声)
mae=2.49
正解: 0.0, 4.0, 8.0, 10.0, -6.0, 4.0, 0.0, -2.0, 1.92, -6.0
推論: 3.01, 2.21, 5.65, 1.14, -4.25, 0.61, 1.76, -0.15, 0.52, -5.14
https://scrapbox.io/files/613def2729a625001facbac4.png
打ってみるとさっきよりまともな手を打つ気がする。まあmaeも低いし…
2021/09/12 21:24
同じモデルで500局、53000盤面で学習
mae=2.24
正解: -4.0, -2.0, 0.0, -2.0, 1.0, -8.0, -4.0, -3.0, 8.0, 12.0
推論: 0.24, -0.29, -0.37, -3.35, 3.62, -2.12, -5.84, -5.27, 5.01, 8.85
https://scrapbox.io/files/613df2bdc557d4001d148ff8.png
打ってみた体感は1000局と同じくらいの精度で打つ感じだった。
2021/09/12 22:00
これまでN局のデータの全ての局面をきっかり使っていたが、N局のデータM個のうち、M/2個くらいをランダムに選んで使うようにしてみた。
2000局のデータのうち選んだ94000盤面で学習
mae=3.54
正解: -6.0, -2.0, -7.5, -21.0, -8.0, -6.67, 10.0, -2.0, -4.0, 0.0
推論: -2.93, -5.13, 0.76, -5.95, -7.89, -2.03, 0.33, -3.17, 0.33, -2.24
https://scrapbox.io/files/613dfc1c2a4a73001d0e7726.png
1000局のデータ全てを使って88000盤面で学習するとmae=2.49であったことを考えると、明らかに精度が落ちた。
これで「少ないデータで学習した方が精度が上がる」現象の原因が判明した。
これまでのデータ生成手法では、特に学習データ(局数)を少なくすると、学習データの中にテストデータと同じ対戦のデータが高確率で紛れ込む。これによってこのNNは半ば、「テストとして来た盤面を見て、学習データの中にある同じ対戦のデータを探す」ような状態になっていたのだ。まあ厳密には全然違うけど。
とにかくこれは非常に良くないし、これまでのmaeの値の良さの割にはAIが弱い原因も多分これだとわかった。
今後は学習データに使う棋譜とテストデータに使う棋譜を完全に分離することにする。そうすればこの問題は解決するので。
2021/09/13 0:50
学習とテストのデータを棋譜レベルで完全に分離した。1000局79000盤面を学習データとして使用。
テストでのmae=4.95
正解: 10.0, -10.0, -2.0, -4.0, 20.0, 6.0, 0.0, -12.0, 0.0, -4.0
推論: 3.91, 0.21, -9.98, -0.49, 6.96, 2.73, -2.97, 1.71, -2.58, -0.73
https://scrapbox.io/files/613e21e524d96e001d5c3137.png
ちなみに学習中のval_maeは3.27まで落ちていたので、やはりval_maeとテストデータのmaeは別みたい(それはそうで分離率を設定していた)
ぶっちゃけ精度がだめだめなので本格的に考え直しが必要か。。
2021/09/13 1:36
上と同じモデルで2500局17万盤面で学習。
mae=4.18
正解: 2.0, -8.0, 2.0, -2.0, -4.0, -2.0, -2.0, -8.0, -2.0, -8.0
推論: -2.94, -1.63, -2.02, -1.75, -0.27, -0.32, 3.15, -1.67, -5.79, -0.81
https://scrapbox.io/files/613e304fcee35b001d65d8ab.png
さっきよりはマシだがval_maeもすぐに3.40くらいに収束してしまったので微妙な気持ちがする。
データは大量にあるのでデータを増やすのと、やはりモデルを大きくする必要があるかもしれない…とても嫌だが…
大きなモデルを作った場合、蒸留をもう一度考えてみても良いかもしれない。もしかしたらうまくいくかも。
このモデルと対戦してみたが、とても弱かった。さすがに精度が悪すぎるので…
2021/09/13 2:00
気になったので何も学習していない状態(1エポックだけ学習)で推論してみた。
mae=4.16
つまり上のはテストデータについては全く使い物にならないモデルだったというわけか…
2021/09/13 2:03
中間層を128-128-128にした。層もニューロンも増やした。
2500局17万盤面で学習
mae=4.10
-6.0, 6.0, -2.0, -12.0, -3.0, -3.0, 2.0, -2.0, -12.0, -10.0
1.36, -1.08, 2.7, -3.31, -0.47, -1.22, 2.03, 1.27, -3.19, -0.44
https://scrapbox.io/files/613e3638cee35b001d65f432.png
だめだこりゃ。
2021/09/13 22:38
val_lossについて調べたら訓練データの最終validation_split分を使うらしい。つまり、上の実験でval_lossとされているのは少なからず訓練データと同じ対戦なので、、、そう、良くないのである…
このあたりの問題を解消するのがとても大変なので、各対戦について小さい定数X盤面だけ選び出して学習データとして使うしかないかもしれない。まあ正直データ数が多いのでこんなに贅沢な使い方をしても悪くはないだろう。
棋譜の読み込みから盤面を復元するのが非常に面倒なので、各棋譜についてとりあえず1万局くらい最終石差と各盤面を別のファイルに保存することにした。
https://scrapbox.io/files/613f56ddf701b6001d0c3fbe.png
↑こんな感じ。1対戦4kBくらいらしいので、12万局を全部解凍すると500MBいかないくらいか。
とりあえず1万局だけ解凍した。Pythonだしファイルアクセスしているので普通に遅い…
2021/09/13 23:05
上のどこかで手番逆転が意味ないとか書いたが、それはそうなのだが、手番が必ず入力データのrv.gridが0になる方にしないと色々まずいことに気づいた。だめだめじゃん…
2021/09/14 0:39
解凍できたので10000局から各局10%ずつデータを取って18000盤面で学習したが…
一応mae=4.82
https://scrapbox.io/files/613f70aab4e50d001d708a64.png
見るからに過学習だがそもそもデータ少ないし、そう言えば中間層128-128-128で学習させていた。
とりあえずモデルを小さくしてデータも増やして再度学習しましょうね
2021/09/14 8:34
10万局解凍できたので10万局から各局10%ずつデータを取ってきて15万盤面で学習。
モデルは中間層128-64に縮小した。
mae=4.26
https://scrapbox.io/files/613fe1438abdd1001d9d643d.png
まあ過学習ではあるが…
さすがにひどすぎる。ちょっとデータ生成手法ミスってないか確認する。
2021/09/14 8:44
データ生成で手番を一部逆転しているのに最終石差を逆転していなかった。そりゃ学習できるわけがないわな。ドジすぎる。とりあえず時間がないので1万局だけ解凍して実験する。18000盤面。
mae=4.66
https://scrapbox.io/files/613fe4e6b9de10001dd6bf98.png
いやおかしいだろ…まだ何かミスってないか考える。
2021/09/14 21:16
データ生成で、盤面をランダム回転させた後にデータを生成しているのは良くなくて、回転すれば同じ盤面なのに値が違うということが起こる。盤面回転なしでデータを作ってから盤面の回転を行ったほうが良さそう。
2021/09/14 21:24
データの加工段階でなぜか半分くらいデータを捨てていたことに気がついたので修正。そもそも1万局のデータ使ってるのに18000盤面(1局あたり1.8盤面、つまり3%)な時点でおかしいことに気づくべきだった…
2021/09/14 23:05
1万局、(互いにほとんど関わりのない)17万盤面で学習
モデルは128-64
mae=4.18
https://scrapbox.io/files/6140ac43bbce6a001d4f3592.png
データの解凍は時間がかかるので夜中にやるとして、とりあえず過学習覚悟でモデル複雑にしようかな…(いや、すでに過学習なのだけれど…)
なんかこの学習、遭遇した盤面全て使ってたみたいなので、それで学習できてないのは色々とおかしすぎる。状況としては学習がうまくいっている"ように見えていた"頃と同じはずなので。
2021/09/14 23:53
ベアプログラミングでデバッグしたが基本的に大丈夫そうだったので、一番怪しい盤面回転の処理を抜いて他は23:05と全く同じ条件で実験。
1万局、19万盤面を使用(テストデータを10%から1%にしたので若干データ数が増えてる)
mae=3.35
https://scrapbox.io/files/6140b9cba1b934002376348b.png
まあ一応学習はできているのでOK
2021/09/15 0:04
盤面を10%の確率で使うようにした。1万局、35000盤面。
mae=4.09
https://scrapbox.io/files/6140bac880e003001d2171a6.png
学習しなくなった。まあこれは想定内。
2021/09/15 0:08
全盤面を使うようにして、盤面回転を使用。学習できているのであれば盤面回転は多分バグってないけど、学習できてなかったら盤面回転がバグってるのか、データを4倍(回転のぶん)にしないとわからない。19万盤面。
mae=4.06
https://scrapbox.io/files/6140c2d09ce8ed001dd541df.png
学習できているかとても微妙なので、回転なし&データ数1/4で実験してみる
2021/09/15 0:42
回転なし&2500局、全盤面。59000盤面を使用。
mae=2.81
https://scrapbox.io/files/6140c55ea3de4b002335624a.png
なんか学習できてる~
可能性として盤面回転のバグかこのモデルがやたら回転に弱いことが考えられるので、とりあえず血眼でバグ探し。
2021/09/15 1:09
回転関数を綺麗に書き直し。1万局、全盤面。19万盤面。
mae=4.27
https://scrapbox.io/files/6140cafeb9ee22001df7adbd.png
学習したいっていう意志は感じる。
まあ多分モデルが回転に異様に弱いのかな。
2021/09/15 2:29
とりあえずテスト/訓練を分けた後に回転処理を入れてデータ数を4倍にした(つまりテストのある盤面の回転したものが訓練にあるということはない)
1万局、全盤面。水増し後で78万盤面。
mae=3.84
https://scrapbox.io/files/6140db458de81f00239c50ba.png
val_mae=3.77なのでテストデータのmaeとは若干開きがあるが、とりあえず学習できていることに変わりはないので盤面の回転関係はこの手法を取ることにする。
それと、結果を見るとおそらくライブラリ側で訓練データを並べ替えとかはされてないと思う
あとは明日!
2021/09/15 10:54
とりあえず盤面の採用率を100%から10%に落としてあとは2:29と同じ条件で学習。1万局、13万盤面を使用。
mae=4.03
https://scrapbox.io/files/614156bb94c482001d04257a.png
多分データ不足で学習できてないんだろうなー
5エポック目くらいまでは学習の意志を感じるがそれ以降が完全に過学習の挙動だ…
2021/09/15 11:14
盤面採用率を10%のままで10万局のデータを読み込んでやってみる。データ数的には1万局で100%より少し多くなると思うので。
盤面データは107万程度だった。メモリが枯渇して危険なのでこれ以上この規模の学習をノートPCではやりたくない。
mae=3.96
val_mae=3.95程度(テストデータとほぼ同じ値なのでとても良い)
https://scrapbox.io/files/61416a40987c9d001e903ec4.png
データ数の暴力で学習は成功したがmaeが大きいので、モデルを複雑にする必要がありそう。悲しい。今のモデルは中間層256-128-128なので…
活性化関数などをいじってマシになったら嬉しいな。
それと、盤面採用率を10%からどこまで上げても大丈夫か調査したいところではある。
2021/09/15 16:29
盤面採用率は100%にして、trainで使うデータとvalidationで使うデータとで使用する対戦結果を完全に分離した。これによって棋譜のデータを大量に使えるようにした。チートをしていたとしたらvalidationで一目瞭然なので。
validation_splitでなくてvalidation_dataを使うようにした。
https://scrapbox.io/files/6141a1eea38ece00247793cd.png